package com.tanhua.server.interceptor;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.common.utils.Cache;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 拦截器
 *
 * 进行判断是否需要命中缓存
 * 还是放行进行正常请求
 */
@Component
public class RedisCacheInterceptor implements HandlerInterceptor {

    @Value("${tanhua.cache.enable}")
    private Boolean enable;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.判断配置文件中的默认缓存是否开启
        if (!enable){
            //没有开启缓存，不拦截请求-放行
            return true;
        }

        //2.校验handler是否是HandlerMethod
        if (!(handler instanceof HandlerMethod)){
            //不是，不拦截请求-放行
            return true;
        }

        //3.校验请求是否是GET请求
        if (!((HandlerMethod)handler).hasMethodAnnotation(GetMapping.class)){
            //不是Get请求
            return true;
        }

        //4.校验请求是否有Cache注解
        if (!((HandlerMethod)handler).hasMethodAnnotation(Cache.class)){
            //没有@Cache注解
            return true;
        }

        /**
         * 5.查询redis中有没有对应的数据
         *  有：直接返回该数据
         *  没有：正常请求，然后缓存到redis中
         */
        //生成redisKey
        String redisKey = createRedisKey(request);
        //查询数据
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //校验redis中的数据是否为null
        if (StringUtils.isEmpty(redisValue)){
            //为null，表示redis中没有缓存数据，就正常访问
            return true;
        }

        // 将redis中的数据进行返回
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.getWriter().write(redisValue);
        //拦截请求
        return false;
    }

    /**
     * 生成redisKey
     * 规则：SERVER_CACHE_DATA_MD5(url + param + token)
     * (直接CV的)
     * @param request
     * @return
     */
    public static String createRedisKey(HttpServletRequest request) throws Exception {
        String url = request.getRequestURI();
        String param = MAPPER.writeValueAsString(request.getParameterMap());
        String token = request.getHeader("Authorization");

        String data = url + "_" + param + "_" + token;
        return "SERVER_CACHE_DATA_" + DigestUtils.md5Hex(data);
    }
}
